﻿using System;
using System.Reflection;
using System.Xml;
using System.IO;
using System.Collections.Generic;
using System.Web;
using Grishko.DataTier;
using Grishko.DataTier.SqlSentence;
using System.Text;

namespace Grishko.SerilizeTools
{
   

    /// <summary>
    /// Static tools of Entity    
    /// </summary>
    public class ReflectionItem : EntityActivator
    {   
        public static bool IsEnum(PropertyInfo inf)
        {
            if (null == inf.PropertyType.BaseType)
                return false;

            return (inf.PropertyType.BaseType.FullName.IndexOf("System.Enum") > -1);
        }

        /// <summary>
        /// Втуренний инструмент. Определяет поддерживает и объект ISerializableItem.
        /// </summary>
        /// <remarks>Используется при серилизации/десерилизации</remarks>
        protected static bool PropertyIsSerializableItem(Type PropType)
        {
            if (null == PropType) return false;

            Type[] ArrType = PropType.GetInterfaces();
            return ImSupprotType(ArrType, typeof(IEntity));
        }

        /// <summary>
        /// Вычислить - входит ли свойство  в заданный массив свойств.
        /// </summary>
        /// <param name="FullList"></param>
        /// <param name="SupportType"></param>
        /// <returns></returns>
        protected static bool ImSupprotType(Type[] FullList, Type SupportType)
        {
            try
            {
                foreach (Type t in FullList)
                {
                    if (t.Equals(SupportType)) return true;
                }
                return false;
            }
            catch
            {
                return false;
            }

        }

        /// <summary>
        /// Вернуть тип примитива
        /// </summary>
        /// <param name="inf"></param>
        /// <returns></returns>
        protected static SrchItemInfo.PropertyControlType GetAttPropertyType(PropertyInfo inf)
        {
            if (inf.PropertyType.Equals(typeof(Decimal)) || inf.PropertyType.Equals(typeof(int))) 
                                return SrchItemInfo.PropertyControlType.Number ;
            if(inf.PropertyType.Equals(typeof(DateTime)))
                                return SrchItemInfo.PropertyControlType.Date ;
            if(inf.PropertyType .Equals (typeof(Boolean)))
                                return SrchItemInfo.PropertyControlType.Bool ;
            if (inf.PropertyType.Equals(typeof(TreeValueProperty)))
                                return SrchItemInfo.PropertyControlType.Tree;

            return SrchItemInfo.PropertyControlType .Text  ;
        }

        /// <summary>
        /// Свойство примитив?
        /// </summary>
        /// <param name="inf"></param>
        /// <returns></returns>
        public static bool  ImAttProperty(PropertyInfo inf)
        {
            return (  inf.PropertyType.Equals(typeof(String)) |
                      inf.PropertyType.Equals(typeof(Double)) |
                      inf.PropertyType.Equals(typeof(Decimal)) |
                      inf.PropertyType.Equals(typeof(DateTime)) |
                      inf.PropertyType.Equals(typeof(Boolean)) |
                      inf.PropertyType.Equals(typeof(int)) 
                   );
        }
       
        /// <summary>
        /// Свойство серелизуемео?
        /// </summary>
        /// <param name="inf"></param>
        /// <returns></returns>
        protected  static bool ImSerisableAtt(PropertyInfo inf)
        {
            if(ImEntityNonSerialized(inf)) return false ;

            return ImAttProperty(inf) |inf.PropertyType.Equals(typeof(object));
        }
        
        
                
        /// <summary>
        /// вернуть список сереизуемых примитивов указанного типа        /// </summary>
        /// <param name="tp"></param>
        /// <returns></returns>
        protected static List<PropertyInfo> GetSerisableAttProperties(Type tp)
        {
            List<PropertyInfo> res = new List<PropertyInfo>(); 
            foreach (PropertyInfo inf in tp.GetProperties())
            {
                if (ImSerisableAtt(inf)) res.Add(inf);
            }
            return res;

        }
        
        /// <summary>
        /// Вернуть серелизуемые Entity свойства 
        /// Имеющие атрибуты из списка InclideTypes  и не имеющие атрибуты списка ExludeTypes
        /// </summary>
        /// <param name="InclideType"></param>
        /// <param name="ExludeTypes"></param>
        /// <returns></returns>
        protected static List<PropertyInfo> GetSerisablePropertyList( Type ObjectType,Type PropIsType, Type[] InclideAttTypes , Type[] ExludeAttTypes)
        {

            List<PropertyInfo> res = new List<PropertyInfo>();

            foreach (PropertyInfo inf in ObjectType.GetProperties())
            {
                //Entity? 
                if (! MemberIsEntity(inf))
                                                continue ; 

                // Имеет не нужные  атрибуты - нах 
                if (MemberInAttType (inf,ExludeAttTypes)) 
                                                continue;
                
                //Без атрибутов
                if(InclideAttTypes.Length ==0)
                                            res.Add(inf);
                // Имеет нужные - добавим
                if (MemberInAttType (inf,InclideAttTypes)) 
                                                res.Add(inf);
            }

            return res;


        }
        
        /// <summary>
        /// Свойство поодерживаеет IEntity
        /// </summary>
        /// <param name="inf"></param>
        /// <returns></returns>
        internal  static bool MemberIsEntity(PropertyInfo  inf )
        {
            return !(null == inf.PropertyType.GetInterface("IEntity"));
            
        }

        /// <summary>
        /// Свойство is  TreeDictionaryItemValue
        /// </summary>
        /// <param name="inf"></param>
        /// <returns></returns>
        internal static bool MemberIsTreeValue(PropertyInfo inf)
        {
            return !(null == inf.PropertyType.GetInterface("ITreeDictionaryItemValue"));

        }        

       /// <summary>
        /// свойство примитив и имеет атрибуты указанные в списке InclideAttTypes
       /// </summary>
       /// <param name="inf"></param>
       /// <param name="InclideAttTypes"></param>
       /// <returns></returns>
        protected  static bool MemberInAttType(MemberInfo inf, Type[] InclideAttTypes)
        {
            foreach (Type t in InclideAttTypes)
            {                
                if (inf.IsDefined(t, false))
                            return true;
            }
            return false;
        }
        
        /// <summary>
        /// возвращает список свойств типа указанного в TypeName
        /// Пддерживающих интерфейс (если InterFaceName=string.empty) не учитывается
        /// </summary>
        /// <param name="tp"></param>
        /// <returns></returns>
        protected static List<PropertyInfo> GetPropertyList(Type ObjectType, string InterFaceName,Type Attribute )
        {
            List<PropertyInfo> res = new List<PropertyInfo>();
            foreach (PropertyInfo inf in ObjectType.GetProperties())
            {
                if (ImEntityNonSerialized(inf)) continue;
                
                if (null!=Attribute)
                        if (!inf.IsDefined(Attribute, true)) continue;

                if (InterFaceName == string.Empty) 
                        { res.Add(inf); continue; }
                
                if (ImSupposeInterface(inf.PropertyType, InterFaceName)) 
                        res.Add(inf);
            }
            return res;

        }
        
        /// <summary>
        /// Возвращает методы помеченные атрибутом указанным в Attribute
        /// </summary>
        /// <param name="ObjectType"></param>
        /// <param name="Attribute"></param>
        /// <returns></returns>
        protected static List<MethodInfo> GetMethodList(Type ObjectType,  Type Attribute)
        {
            List<MethodInfo> res = new List<MethodInfo>();

            foreach (MethodInfo inf in ObjectType.GetMethods() )
            {                
                if (!inf.IsDefined(Attribute, true)) continue;                
                res.Add(inf);
            }

            return res;

        }
        
        /// <summary>
        /// Я не сериизуемое свойство  
        /// </summary>
        /// <param name="inf"></param>
        /// <returns></returns>
        protected static bool ImEntityNonSerialized(PropertyInfo inf)
        {
            
            return inf.IsDefined(typeof(EntityNonSerialized), true);
        }


        //protected static bool ImIsInterfaceEntity(PropertyInfo inf)
        //{
        //    return inf.IsDefined(typeof(IsInterfaceEntity), true);
        //}

        /// <summary>
        /// Я поодерживаю интерфейс InterfaceName
        /// </summary>
        /// <param name="tp"></param>
        /// <param name="InterfaceName"></param>
        /// <returns></returns>
        protected static bool ImSupposeInterface(Type tp, string InterfaceName)
        {
            foreach (Type item in tp.GetInterfaces())
            {
                if (item.ToString().IndexOf(InterfaceName) > -1) return true;
            }
            return false;
        }

        

    }

}
